home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / debugger / ddd-1.000 / ddd-1 / ddd-1.4b / ddd / LineGraphE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-21  |  6.7 KB  |  251 lines

  1. // $Id: LineGraphE.C,v 1.6 1995/11/21 13:50:25 zeller Exp $
  2. // class LineGraphEdge
  3.  
  4. // Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller (zeller@ips.cs.tu-bs.de).
  6. // 
  7. // This file is part of the DDD Library.
  8. // 
  9. // The DDD Library is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU Library General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // The DDD Library is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU Library General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU Library General Public
  20. // License along with the DDD Library -- see the file COPYING.LIB.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 675 Mass Ave, Cambridge, MA 02139, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers at `ddd@ips.cs.tu-bs.de'.
  28.  
  29. char LineGraphEdge_rcsid[] = 
  30.     "$Id: LineGraphE.C,v 1.6 1995/11/21 13:50:25 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36.  
  37. #include "assert.h"
  38.  
  39. #include <math.h>
  40. #include <limits.h>
  41. #include <string.h>
  42. #include <stdlib.h>
  43.  
  44. #include <X11/X.h>
  45. #include <X11/Xlib.h>
  46. #include <X11/Intrinsic.h>
  47.  
  48. #include "LineGraphE.h"
  49. #include "GraphNode.h"
  50.  
  51. DEFINE_TYPE_INFO_1(LineGraphEdge, GraphEdge)
  52.  
  53. // find the points to draw line at
  54.  
  55. enum Side { North = 1, South = 2, East = 4, West = 8 };
  56.  
  57. // Clip point <p> to side <side> of region <b>
  58. static void moveToSide(BoxRegion& b, int side, BoxPoint& p, BoxPoint&)
  59. {
  60.     assert(side == North || side == South || side == East || side == West);
  61.  
  62.     p = b.origin();
  63.  
  64.     // fetch points
  65.     if (side & (North | South))
  66.     {
  67.     p[X] += b.space(X) / 2;
  68.     if (side & South)
  69.         p[Y] += b.space(Y);
  70.     }
  71.  
  72.     if (side & (East | West))
  73.     {
  74.     p[Y] += b.space(Y) / 2;
  75.     if (side & East)
  76.         p[X] += b.space(X);
  77.     }
  78. }
  79.  
  80.  
  81. // Clip point <p> to side <side> of region <b> centered around <c>
  82. static void clipToSide(BoxRegion& b, int side, BoxPoint& p, BoxPoint& c)
  83. {
  84.     assert(side == North || side == South || side == East || side == West);
  85.  
  86.     BoxDimension d1, d2;
  87.  
  88.     if (side & (North | South))
  89.     d1 = X, d2 = Y;
  90.     else
  91.     d1 = Y, d2 = X;
  92.  
  93.     int offset;
  94.     if (side & (North | West))
  95.     offset = -1;
  96.     else
  97.     offset = 1;
  98.  
  99.     if (c[d1] != p[d1] && c[d2] != p[d2])
  100.     p[d1] += offset * (b.space(d2) / 2) * (c[d1] - p[d1]) 
  101.         / (c[d2] - p[d2]);
  102.     p[d2] += offset * b.space(d2) / 2;
  103. }
  104.  
  105.  
  106. // Clip point <p> to side <side> of region <b> centered around <c>
  107. // Assume that b contains a circle
  108. static void clipToCircle(BoxRegion& b, int /* side */, 
  109.              BoxPoint& p, BoxPoint& c)
  110. {
  111.     // assert(side == North || side == South || side == East || side == West);
  112.  
  113.     double radius = max(b.space(X), b.space(Y)) / 2;
  114.     if (radius > 0.0)
  115.     {
  116.     double hyp = hypot(c[X] - p[X], c[Y] - p[Y]);
  117.  
  118.     p[X] += BoxCoordinate((radius * (c[X] - p[X])) / hyp);
  119.     p[Y] += BoxCoordinate((radius * (c[Y] - p[Y])) / hyp);
  120.     }
  121. }
  122.  
  123.  
  124. typedef void (*ClipProc)(BoxRegion& b, int side, BoxPoint& p, BoxPoint& c);
  125.  
  126. struct ClipMapRec {
  127.     EdgeAttachMode mode;
  128.     ClipProc       proc;
  129. };
  130.  
  131. const ClipMapRec clipMap[] = {
  132.     {Straight, clipToSide},
  133.     {Circle,   clipToCircle},
  134.     {Centered, moveToSide}
  135. };
  136.  
  137. // Find line from region <b1> centered around <c1>
  138. // to region <b2> centered around <c2>
  139. // Resulting line shall be drawn from <p1> to <p2>
  140. void LineGraphEdge::findLine(BoxPoint& c1, BoxPoint& c2,
  141.                  BoxRegion& b1, BoxRegion& b2, 
  142.                  BoxPoint& p1, BoxPoint& p2, 
  143.                  const GraphGC& gc)
  144. {
  145.     // allow all sizes to begin
  146.     int side1 = North | South | East | West;
  147.     int side2 = North | South | East | West;
  148.  
  149.     // exclude opposite side
  150.     if (c2[X] > c1[X]) { side1 &= ~West; side2 &= ~East; }
  151.     else               { side1 &= ~East; side2 &= ~West; }
  152.  
  153.     if (c2[Y] > c1[Y]) { side1 &= ~North; side2 &= ~South; }
  154.     else               { side1 &= ~South; side2 &= ~North; }
  155.  
  156.     // find edge cutting the line between the two center points c1, c2
  157.     BoxCoordinate dx = abs(c1[X] - c2[X]);
  158.     BoxCoordinate dy = abs(c1[Y] - c2[Y]);
  159.  
  160.     if (b1.space(Y) * dx > b1.space(X) * dy) side1 &= ~(North | South);
  161.     else                                     side1 &= ~(East | West);
  162.  
  163.     if (b2.space(Y) * dx > b2.space(X) * dy) side2 &= ~(North | South);
  164.     else                                     side2 &= ~(East | West);
  165.  
  166.     p1 = c1;
  167.     p2 = c2;
  168.  
  169.     // select appropriate clipping procedure
  170.     for (int i = 0; i < int(sizeof(clipMap)/sizeof(clipMap[0])); i++)
  171.     if (gc.edgeAttachMode == clipMap[i].mode)
  172.     {
  173.         clipMap[i].proc(b1, side1, p1, c2);
  174.         clipMap[i].proc(b2, side2, p2, c1);
  175.  
  176.         return;
  177.     }
  178.  
  179.     assert(0);
  180. }
  181.  
  182.  
  183. // Draw
  184.  
  185. void LineGraphEdge::_draw(Widget w, 
  186.               const BoxRegion&, 
  187.               const GraphGC& gc) const
  188. {
  189.     // Get node starting points
  190.     BoxPoint pos1     = from()->pos();
  191.     BoxRegion region1 = from()->region(gc);
  192.     if (from()->selected())
  193.     {
  194.     pos1             += gc.offsetIfSelected;
  195.     region1.origin() += gc.offsetIfSelected;
  196.     }
  197.  
  198.     BoxPoint pos2     = to()->pos();
  199.     BoxRegion region2 = to()->region(gc);
  200.     if (to()->selected())
  201.     {
  202.     pos2             += gc.offsetIfSelected;
  203.     region2.origin() += gc.offsetIfSelected;
  204.     }
  205.  
  206.     // If nodes overlap, don't draw the edge.
  207.     if (region1 <= region2)
  208.     return;
  209.  
  210.     // Get the line points
  211.     BoxPoint l1, l2;
  212.     findLine(pos1, pos2, region1, region2, l1, l2, gc);
  213.  
  214.     // If there is no edge (adjacent nodes), don't draw it.
  215.     if (l1 == l2)
  216.     return;
  217.  
  218.     XDrawLine(XtDisplay(w), XtWindow(w), gc.edgeGC,
  219.     l1[X], l1[Y], l2[X], l2[Y]);
  220.  
  221.     if (gc.drawArrowHeads && !to()->isHint())
  222.     {
  223.     // draw arrowhead at l2
  224.  
  225.     const double offset = gc.arrowAngle * M_PI/180;    // angle
  226.     const int length    = gc.arrowLength;        // length
  227.  
  228.         // get arrow angle
  229.     double alpha = atan2(l1[Y] - l2[Y], l1[X] - l2[X]);
  230.  
  231.         // get coordinates
  232.     XPoint points[3];
  233.     points[0].x = l2[X];
  234.     points[0].y = l2[Y];
  235.     points[1].x = (short)(l2[X] + length * cos(alpha + offset / 2));
  236.     points[1].y = (short)(l2[Y] + length * sin(alpha + offset / 2));
  237.     points[2].x = (short)(l2[X] + length * cos(alpha - offset / 2));
  238.     points[2].y = (short)(l2[Y] + length * sin(alpha - offset / 2));
  239.  
  240. #if 0
  241.         cout << "\nalpha = " << alpha / M_PI * 360 << "\n";
  242.     for (int i = 0; i < 3; i++)
  243.         cout << "points[" << i << "] = "
  244.         << BoxPoint(points[i].x, points[i].y) << "\n";
  245. #endif
  246.  
  247.     XFillPolygon(XtDisplay(w), XtWindow(w), gc.edgeGC, points, 
  248.              XtNumber(points), Convex, CoordModeOrigin);
  249.     }
  250. }
  251.